﻿using System;
using System.Collections.Generic;
using System.Linq;

using NHibernate.Criterion;

using Inovout.Runtime;
using Inovout.Services;

using Inovout.Cloud.DataStore.Models;
using Inovout.Cloud.DataStore.Utility;

namespace Inovout.Cloud.DataStore.Services
{
    public class PropertyService : RepositoryService<Inovout.Cloud.DataStore.Models.Property>, IPropertyService
    {
        //private MongoDbClient _mongoDbClient;
        //protected MongoDbClient MongoDbClient
        //{
        //    get
        //    {
        //        if (_mongoDbClient == null)
        //        {
        //            _mongoDbClient = new MongoDbClient(ComponentRegistry.Resolve<IApplication>().Settings["MongoDbConnectionString"].ToString());
        //        }

        //        return _mongoDbClient;
        //    }
        //}

        /// <summary>
        /// 取得表的所有字段
        /// </summary>
        /// <param name="databaseName">数据库名</param>
        /// <param name="tableName">表名</param>
        /// <returns></returns>
        public IEnumerable<Models.Property> GetProperties(String databaseName, String tableName)
        {
            DatabaseService databaseService = (DatabaseService)ComponentRegistry.Resolve<IDatabaseService>();
            TableService tableService = (TableService)ComponentRegistry.Resolve<ITableService>();
            Database database = databaseService.FindByName(databaseName);
            if (database == null)
            {
                return null;
            }

            Iesi.Collections.Generic.ISet<Table> tables = database.Tables;
            if (tables == null || tables.Count == 0)
            {
                return null;
            }

            Table dataStoreTable = null;
            foreach (Table table in tables)
            {
                if (table.Name.ToLower().Equals(tableName.ToLower()))
                {
                    dataStoreTable = table;
                    break;
                }
            }

            if (dataStoreTable == null)
            {
                return null;
            }

            return dataStoreTable.Properties;

        }

        /// <summary>
        /// 取得表的所有字段
        /// </summary>
        /// <param name="table"></param>
        /// <returns></returns>
        public IEnumerable<Models.Property> GetProperties(Table table)
        {
            if (table == null)
            {
                return null;
            }

            return base.Repository.FindAll(Restrictions.Eq("Table.Id", table.Id));
        }

        /// <summary>
        /// 取得字段的定义
        /// </summary>
        /// <param name="table"></param>
        /// <param name="propertyName"></param>
        /// <returns></returns>
        public Inovout.Cloud.DataStore.Models.Property GetProperty(Table table, string propertyName)
        {
            if (table == null || String.IsNullOrEmpty(propertyName))
            {
                return null;
            }

            return base.Repository.Find(Restrictions.Eq("Table.Id", table.Id),
                                            Restrictions.Eq("Name", propertyName).IgnoreCase());
        }

        // <summary>
        /// 创建一个字段
        /// </summary>
        /// <param name="property"></param>
        public void CreateProperty(Models.Property property)
        {
            Models.Property pro = GetProperty(property.Table, property.Name);
            if (pro != null)
            {
                return;
            }

            base.Create(property);
        }

        /// <summary>
        /// 批量创建字段
        /// </summary>
        /// <param name="properties"></param>
        public void CreateProperties(List<Models.Property> properties)
        {
            if (properties == null || properties.Count() == 0)
            {
                return;
            }

            foreach (Models.Property property in properties)
            {
                CreateProperty(property);
            }
        }

        /// <summary>
        /// 修改字段类型
        /// </summary>
        /// <param name="table"></param>
        /// <param name="property"></param>
        /// <returns></returns>
        public Models.Property UpdateProperty(Table table, Models.Property property)
        {
            Models.Property oldProperty = GetProperty(table, property.Name);
            if (oldProperty == null)
            {
                return null;
            }

            oldProperty.FieldType = property.FieldType;
            oldProperty.IsPrimaryKey = property.IsPrimaryKey;
            base.Update(oldProperty);

            return oldProperty;
        }

        /// <summary>
        /// 批量更新表的字段
        /// </summary>
        /// <param name="table"></param>
        /// <param name="properties"></param>
        public void UpdateProperties(Table table, List<Models.Property> properties)
        {
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            foreach (Models.Property property in properties)
            {
                UpdateProperty(table, property);
            }
        }

        /// <summary>
        /// 保存字段
        /// </summary>
        /// <param name="table"></param>
        /// <param name="property"></param>
        public void SaveProperty(Table table, Models.Property property)
        {
            Models.Property oldProperty = GetProperty(table, property.Name);
            if (oldProperty == null)
            {
                base.Create(property);
            }
            else
            {
                oldProperty.FieldType = property.FieldType;
                oldProperty.IsPrimaryKey = property.IsPrimaryKey;
                base.Update(oldProperty);
            }
        }

        /// <summary>
        /// 批量保存字段
        /// </summary>
        /// <param name="table"></param>
        /// <param name="properties"></param>
        public void SaveProperties(Table table, List<Models.Property> properties)
        {
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            foreach (Models.Property property in properties)
            {
                Models.Property oldProperty = GetProperty(table, property.Name);
                if (oldProperty == null)
                {
                    base.Create(property);
                }
                else
                {
                    oldProperty.FieldType = property.FieldType;
                    oldProperty.IsPrimaryKey = property.IsPrimaryKey;
                    base.Update(oldProperty);
                }
            }
        }

        /// <summary>
        /// 用新的替换原有的所有Properties
        /// </summary>
        /// <param name="table"></param>
        /// <param name="properties"></param>
        public void ReplaceAllProperties(Table table, List<Models.Property> properties)
        {
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            DropAllProperties(table);
            CreateProperties(properties);
        }

        /// <summary>
        /// 根据主键删除
        /// </summary>
        /// <param name="id">主键</param>
        public void DropProperty(object id)
        {
            Models.Property property = base.FindById(id);
            if (property != null)
            {
                property.Table.Properties.Remove(property);
                base.Delete(id);
            }
            
        }

        /// <summary>
        /// 删除字段
        /// </summary>
        /// <param name="table"></param>
        /// <param name="propertyName"></param>
        public void DropProperty(Table table, string propertyName)
        {
            Models.Property oldProperty = GetProperty(table, propertyName);
            if (oldProperty == null)
            {
                return;
            }

            //删除MongoDb中该列名的所有值
            //this.MongoDbClient.RemoveField(table.Database.Name, table.Name, propertyName);

            //删除SqlServer中表的属性定义
            oldProperty.Table.Properties.Remove(oldProperty);
            base.Delete((Object)oldProperty.Id);
        }

        /// <summary>
        /// 删除指定的字段定义
        /// </summary>
        /// <param name="table"></param>
        /// <param name="properties"></param>
        public void DropProperties(Table table, List<Models.Property> properties)
        {
            if (properties == null || properties.Count == 0)
            {
                return;
            }

            foreach (Models.Property property in properties)
            {
                DropProperty(table, property.Name);
            }
        }

        /// <summary>
        /// 删除指定的字段定义
        /// </summary>
        /// <param name="table"></param>
        /// <param name="propertyNames"></param>
        public void DropProperties(Table table, List<string> propertyNames)
        {
            if (propertyNames == null || propertyNames.Count == 0)
            {
                return;
            }

            foreach (String propertyName in propertyNames)
            {
                DropProperty(table, propertyName);
            }
        }

        /// <summary>
        /// 删除表的所有字段定义
        /// </summary>
        /// <param name="table"></param>
        public void DropAllProperties(Table table)
        {
            IEnumerable<Models.Property> properties = GetProperties(table);
            if (properties == null || properties.Count() == 0)
            {
                return;
            }

            //删除MongoDb中该列名相同的所有数据
            //MongoDbClient.RemoveAllEntities(table.Database.Name, table.Name);

            //删除SqlServer中表的属性定义
            foreach (Models.Property property in properties)
            {
                property.Table.Properties.Remove(property);
                base.Delete((Object)property.Id);
            }
        }
    }
}
